/** 判断数据类型 **/
function checkDataType(val) {
  return Object.prototype.toString.call(val).slice(8, -1);
}

/** 数据检测相关包 **/
export const CheckUtil = {
  isString(val) {
    return checkDataType(val) === 'String';
  },

  // NaN, Infinity, -Infinity 不算做 Number
  isNumber(val) {
    return checkDataType(val) === 'Number' && isFinite(val) && !isNaN(val);
  },

  isBoolean(val) {
    return checkDataType(val) === 'Boolean';
  },

  isSymbol(val) {
    return checkDataType(val) === 'Symbol';
  },

  isUndefined(val) {
    return checkDataType(val) === 'Undefined';
  },

  isNull(val) {
    return checkDataType(val) === 'Null';
  },

  isFunction(val) {
    return checkDataType(val) === 'Function';
  },

  isDate(val) {
    return checkDataType(val) === 'Date';
  },

  isArray(val) {
    return checkDataType(val) === 'Array';
  },

  /** 原生对象(非数组、日期等) **/
  isPlainObject(val) {
    return checkDataType(val) === 'Object';
  },

  /** 对象（包含数组，日期等） **/
  isObject(val) {
    return val instanceof Object;
  },

  isFormData(val) {
    return checkDataType(val) === 'FormData';
  },

  isRegExp(val) {
    return checkDataType(val) === 'RegExp';
  },

  isError(val) {
    return checkDataType(val) === 'Error';
  },

  isHTMLDocument(val) {
    return checkDataType(val) === 'HTMLDocument';
  },

  isFile(val) {
    return checkDataType(val) === 'File';
  },

  isPromise(val) {
    return this.isDef(val) && typeof val.then === 'function' && typeof val.catch === 'function';
  },

  /** 是否浏览器环境 **/
  isBrowser() {
    return typeof window !== 'undefined';
  },

  /** 是否 Node 环境 **/
  isNode() {
    return typeof global !== 'undefined';
  },

  /** 是否简单类型（undefined, null, string, number, boolean） **/
  isSimple(val) {
    return this.isUndefined(val) || this.isNull(val) || this.isString(val) || this.isNumber(val) || this.isBoolean(val);
  },
  /** 是否是undefined或者null */
  isUndef(val) {
    return val === undefined || val === null;
  },

  /** 是否不是undefined或者null */
  isDef(val) {
    return !this.isUndef(val);
  },

  /** 是否是纯数值字符串，注意 0 **/
  isNumberString(val) {
    const n = Number(val);
    return this.isString(val) && (n === 0 || !!n);
  },

  /** 是否是日期格式字符串 **/
  isDateString(val) {
    return this.isString(val) && !isNaN(Date.parse(val));
  },

  /** 是否是空字符串 **/
  isEmptyString(val) {
    return this.isString(val) && val.length === 0;
  },

  /** 是否是非空字符串（纯空格字符串视为空字符串） **/
  isNotEmptyString(val) {
    return this.isString(val) && val.trim().length > 0;
  },

  /** 是否是纯数值字符串或数值 **/
  isLikeNumber(val) {
    return this.isNumberString(val) || this.isNumber(val);
  },

  /** 是否是日期对象或日期格式字符串 **/
  isLikeDate(val) {
    return this.isDateString(val) || this.isDate(val);
  },

  isInt(num) {
    return this.isNumber(num) && num === Math.floor(num);
  },

  isFloat(num) {
    return this.isNumber(num) && num !== Math.floor(num);
  },

  /** 是否是空数组 **/
  isEmptyArray(val) {
    return this.isArray(val) && val.length === 0;
  },

  /** 是否非空数组 **/
  isNotEmptyArray(val) {
    return this.isArray(val) && val.length > 0;
  },

  /** 是否只包含简单类型的数组 **/
  isSimpleArray(val) {
    return this.isArray(val) && val.every((item) => this.isSimple(item));
  },

  /** 是否只包含对象（null不算）的数组 **/
  isObjectArray(val) {
    return this.isArray(val) && val.every((item) => this.isPlainObject(item));
  },

  /** 是否是空对象 **/
  isEmptyObject(val) {
    return this.isPlainObject(val) && Object.keys(val).length === 0;
  },

  /** 是否是空对象 **/
  isNotEmptyObject(val) {
    return this.isPlainObject(val) && Object.keys(val).length > 0;
  },

  /** 是否值只包含简单类型对象 **/
  isSimplePlainObject(val) {
    return this.isPlainObject(val) && Object.keys(val).every((key) => this.isSimple(val[key]));
  },

  /**
   * 是否空数据
   *    undefined, null,{},[],"",undefined => true; 其他返回 false
   * @param val
   * @returns {boolean}
   */
  isEmpty(val) {
    return this.isUndefined(val) || this.isNull(val) || this.isEmptyString(val) || this.isEmptyArray(val) || this.isEmptyObject(val);
  },

  /**
   * 是否非空
   * @param val
   * @returns {boolean}
   */
  isNotEmpty(val) {
    return !this.isEmpty(val);
  },

  /**
   * 判断两个值是否相等(来自 vue.js)
   * @param a
   * @param b
   * @returns {boolean}
   */
  isEqual(a, b) {
    if (this.isSimple(a) && this.isSimple(b)) {
      return a === b;
    }

    if (this.isObject(a) && this.isObject(b)) {
      if (this.isArray(a) && this.isArray(b)) {
        return a.length === b.length && a.every((item, index) => this.isEqual(item, b[index]));
      } else if (this.isDate(a) && this.isDate(b)) {
        return a.getTime() === b.getTime();
      } else if (this.isPlainObject(a) && this.isPlainObject(b)) {
        const keyAList = Object.keys(a);
        const keyBList = Object.keys(b);
        return keyAList.length === keyBList.length && keyAList.every((key) => this.isEqual(a[key], b[key]));
      } else {
        return false;
      }
    }

    if (!this.isObject(a) && !this.isObject(b)) {
      return String(a) === String(b);
    }

    return false;
  },
};
